﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.IO;
using System.ComponentModel;
using System.Threading;

namespace LearnCSharp_1
{
    class LearnProcess
    {
        private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();

        public static void test1()
        {
            Process process = new Process();
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardInput = true;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
            process.StartInfo.StandardErrorEncoding = Encoding.UTF8;
            process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

            string work_dir_path = Directory.GetCurrentDirectory();
            Logger.Info("work directory path: " + work_dir_path);
            string base_dir_path = AppDomain.CurrentDomain.BaseDirectory;
            Logger.Info("base directory path: " + base_dir_path);

            Directory.SetCurrentDirectory("C:\\Users\\ronal\\Documents\\workspaces\\study\\csharp");
            process.StartInfo.FileName = "hello.exe";
            process.Start();
            process.WaitForExit();
            process.Close();

            Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
        }

        public static void Main_LearnProcess(string[] args)
        {
            ProcessHelper.Run("C:\\Users\\ronal\\Documents\\workspaces\\study\\csharp\\hello.exe", null);
            Console.ReadKey();
        }
    }

    public class ProcessHelper
    {
        public static int WaitTime = 50; // 读取数据的时候等待时间。
        private static Process GetProcess()
        {
            Process process = new Process();
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            process.StartInfo.RedirectStandardInput = true;
            process.StartInfo.RedirectStandardError = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
            process.StartInfo.StandardErrorEncoding = Encoding.UTF8;
            return process;
        }

        public static RunResult Run(string exePath, string args)
        {
            var result = new RunResult();
            using (var p = GetProcess())
            {
                try
                {
                    p.StartInfo.FileName = exePath;
                    p.StartInfo.Arguments = args;
                    p.Start();

                    // 获取正常信息
                    if (p.StandardOutput.Peek() > -1)
                    {
                        result.OutputString = p.StandardOutput.ReadToEnd();
                    }
                    // 获取错误信息
                    if (p.StandardError.Peek() > -1)
                    {
                        result.OutputString = p.StandardError.ReadToEnd();
                    }

                    Thread.Sleep(WaitTime);
                    p.StandardInput.WriteLine("exit\r");
                    // 等待结束
                    p.WaitForExit(WaitTime);
                    result.ExitCode = p.ExitCode;
                    result.Success = true;
                }
                catch (Win32Exception ex)
                {
                    result.Success = false;
                    result.OutputString = string.Format("{0}", ex.NativeErrorCode);
                    Console.Write($"{ex.NativeErrorCode}");
                }
                catch (Exception ex)
                {
                    result.Success = false;
                    result.OutputString = ex.ToString();
                }
                finally
                {
                    try
                    {
                        if (!p.HasExited)
                        {
                            p.Kill();
                        }
                    }
                    catch (Exception ex)
                    {
                        result.MoreOutputString.Add(99999, ex.ToString());
                    }
                }
                return result;
            }
        }
    }

    public class RunResult
    {
        public bool Success;
        public int ExitCode;
        public string OutputString;
        public Dictionary<int, string> MoreOutputString;
        public RunResult()
        {
            OutputString = string.Empty;
            MoreOutputString = new Dictionary<int, string>();
        }

        public new string ToString()
        {
            var str = new StringBuilder();
            str.AppendFormat("Success:{0}\nExitCode:{1}\nOutputString:{2}\nMoreOutputString:\n", Success, ExitCode, OutputString);
            if (MoreOutputString != null)
                foreach (var v in MoreOutputString)
                    str.AppendFormat("{0}:{1}\n", v.Key, v.Value);
            return str.ToString();
        }
    }
}
